Node.js アプリケーションの並列性の最適化
最終更新日 2024年12月04日(水)
Table of Contents
Node の別のコンテナサイズへのスケーリング機能は限られています。シングルスレッドであるため、追加の CPU コアを自動的に利用することはできません。
Node.js アプリがその使用可能なリソースを最大化するには、複数のプロセスをフォークする必要があります。この “クラスタリング” は Node.js Cluster API でサポートされています。Cluster API を使用すると、さまざまな dyno タイプにわたってアプリのパフォーマンスを最適化できます。
Premier または Signature Success Plan の Heroku Enterprise の顧客は、Customer Solutions Architecture (CSA) チームに、このトピックに関する詳細なガイダンスを要求できます。ここでエキスパートコーチングセッションについて学習するか、または Salesforce の担当者にお問い合わせください。
アプリでの並列性の有効化
すべてのアプリケーションでクラスタリングをサポートすることをお勧めします。現在は複数のプロセスの実行を予測していない場合でも、クラスタリングによって、アプリのパフォーマンスに対する制御と柔軟性が向上します。単純なクラスター化されたアプリでこれがどのように機能するかを見てみましょう。
const cluster = require('node:cluster')
const http = require('node:http')
const process = require('node:process')
const numOfWorkers =
process.env.HEROKU_AVAILABLE_PARALLELISM || // for fir-based apps
process.env.WEB_CONCURRENCY || // for cedar-based apps
1
const port = process.env.PORT || 5006
if (cluster.isPrimary) {
console.log(`Primary ${process.pid} is running`)
for (let i = 0; i < numOfWorkers; i++) {
cluster.fork()
}
cluster.on('exit', (worker, code, signal) => {
console.log(`Worker ${worker.process.pid} died`)
})
} else {
http.createServer((req, res) => {
res.writeHead(200)
res.end('hello world\n')
}).listen(port)
console.log(`Worker ${process.pid} started`)
}
上記のコードを server.js
という名前のローカルファイルに保存すると、それを実行してクラスターを観察できます。
$ HEROKU_AVAILABLE_PARALLELISM=4 node server.js
Primary 1779 is running
Worker 1781 started
Worker 1780 started
Worker 1783 started
Worker 1782 started
並列性レベルのチューニング
各アプリにはメモリ、CPU、I/O に関する固有の要件があるため、1 つのサイズですべてを満たすスケーリングソリューションはありません。
クラシック buildpack Node.js アプリ
Heroku buildpack には、WEB_MEMORY
と WEB_CONCURRENCY
の 2 つの環境変数による妥当なデフォルト値が用意されています。どちらも、特定のアプリケーションに適合するように上書きできます。
WEB_MEMORY
は、アプリケーションのプロセスの予測されるメモリ要件 (MB 単位) を指定します。そのデフォルト値は 512 MB です。WEB_CONCURRENCY
は、アプリケーションをクラスタリングするための推奨されるプロセス数を指定します。これは実質的にMEMORY_AVAILABLE / WEB_MEMORY
です。
クラスタリング時のアプリケーションのメモリ使用の設定に関する詳細を参照してください。
デフォルト値
Common Runtime
dyno タイプ | クラスターワーカーの数 |
---|---|
Eco, Basic, Standard-1X | 1 |
Standard-2X | 2 |
Performance-M | 5 |
Performance-L | 28 |
Performance-L-RAM | 15 |
Performance-XL | 31 |
Performance-2XL | 63 |
Private Spaces と Shield Private Spaces
dyno タイプ | クラスターワーカーの数 |
---|---|
Private-S / Shield-S | 2 |
Private-M / Shield-M | 5 |
Private-L / Shield-L | 28 |
Private-L-RAM / Shield-L-RAM | 15 |
Private-XL / Shield-XL | 31 |
Private-2XL / Shield-2XL | 63 |
Performance-L dyno の場合、アプリケーションは、その 14 GB のメモリに推奨される 28 個のワーカーで適切に動作します。常にアプリケーションをテストして、それだけの数の並列プロセスをサポートできるかどうかを確認してください。
これらのデフォルト値は、ほとんどのアプリにとって妥当です。多くの場合、Standard-1X dyno 上での複数のワーカーのクラスタリングはパフォーマンスを向上させるのではなく、むしろ低下させます。ただし、WEB_CONCURRENCY
と dyno サイズの任意の組み合わせを試してみて、実際のワークロードにとって何が最適であるかを確認することができます。
WEB_MEMORY
を減らすと、WEB_CONCURRENCY
が増加します。同様に、WEB_MEMORY
を増やすと並列性が低下します。dyno のサイズが変更されると、使用可能なメモリがいっぱいになるように WEB_CONCURRENCY
が自動的に再計算されます。
WEB_CONCURRENCY
を直接設定することもできますが、これにより、dyno サイズが変更されたときにアプリが自動的に再クラスタリングできなくなります。
Cloud Native Buildpack Node.js アプリ
Heroku の Node.js Cloud Native Buildpack は、HEROKU_AVAILABLE_PARALLELISM
環境変数で使用するクラスターワーカーの数を決定するための適切なデフォルトを提供します。
この値は常に、Fir の dyno にリストされている CPU コアの数と一致します。
Node.js には os.availableParallelism()
を通じて使用するクラスターの適切な数を決定する組み込みメソッドも用意されています。ただし、このコンテナ対応 API は比較的新しいため、Heroku dyno で使用するのに最適な値が常に生成されるとは限りません。